#include "assglParser.h"

#include <iostream>
#include <string.h>

#include "assglUtils.h"

// #define STRVAL(Name) else if (!keyName.compare(#Name)) \ 
//             { \
//                 lib->AssglTrackItem[lib->AssglTrackCounts]. ##Name = valueName; \
//             } \

// #define INTVAL(Name) else if (!keyName.compare(#Name)) \ 
//             {\
//                 lib->AssglTrackItem[lib->AssglTrackCounts]. ##Name = std::stoi(valueName);\
//             }\

#define STRING(x)		std::string(x)

inline void skip_spaces(char **str)
{
    char *p = *str;
    while ((*p == ' ') || (*p == '\t'))
        ++p;
    *str = p;
}

std::string parseEvent(AssglLib *lib, std::string txtData){
	std::string remark;
    if (!strncmp(txtData.c_str(), "Format:", 7)){
        std::string formatStr = txtData.substr(7,txtData.length()-7);
        char *formatC = (char*)formatStr.c_str();
        skip_spaces(&formatC);
        // lib->EventFormat = std::string(formatC);
        // lib->EventFormat = formatC;
        strcpy(lib->EventFormat,formatC);
        lib->AssglTrackCounts = -1;
    }
    else if (!strncmp(txtData.c_str(), "Dialogue:", 9)){
        lib->AssglTrackCounts += 1;
        std::string valueStrQ = txtData.substr(9,txtData.length()-9);
        char *valueC = (char*)valueStrQ.c_str();
        skip_spaces(&valueC);
        std::string valueStr = std::string(valueC);
        int indexof = 0,indexofPre = 0;
        int valueIndexof = 0,valueIndexofPre = 0;
        do{
            if((indexof = STRING(lib->EventFormat).find(",",indexof)) == std::string::npos){
                indexof = STRING(lib->EventFormat).length();
                valueIndexof = valueStr.length();
            }
            std::string keyName = STRING(lib->EventFormat).substr(indexofPre,indexof - indexofPre);
            if (valueIndexof != valueStr.length()){
                valueIndexof = valueStr.find_first_of(",",valueIndexof);
            }
            std::string valueName = valueStr.substr(valueIndexofPre,valueIndexof - valueIndexofPre);
            if (valueName.empty())
                valueName = NOEXIST_STR;
            // std::cout << "keyName:" << keyName << std::endl;
            // std::cout << "valueName:" << valueName << std::endl;
            {
                if (0){}
                else if (!keyName.compare("FontName")) 
                    strcpy(lib->AssglTrackItem[lib->AssglTrackCounts].FontName , valueName.c_str());
                else if (!keyName.compare("FontSize")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].FontSize = std::stoi(valueName);
                else if (!keyName.compare("FontColour")) 
                    strcpy(lib->AssglTrackItem[lib->AssglTrackCounts].FontColour , valueName.c_str());
                else if (!keyName.compare("Outline")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].Outline = std::stoi(valueName);
                else if (!keyName.compare("OutlineColour")) 
                    strcpy(lib->AssglTrackItem[lib->AssglTrackCounts].OutlineColour , valueName.c_str());
                else if (!keyName.compare("BackColour")) 
                    strcpy(lib->AssglTrackItem[lib->AssglTrackCounts].BackColour , valueName.c_str());
                else if (!keyName.compare("Bold")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].Bold = std::stoi(valueName);
                else if (!keyName.compare("Italic")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].Italic = std::stoi(valueName);
                else if (!keyName.compare("Underline")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].Underline = std::stoi(valueName);
                else if (!keyName.compare("StrikeOut")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].StrikeOut = std::stoi(valueName);
                else if (!keyName.compare("Spacing")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].Spacing = std::stoi(valueName);
                else if (!keyName.compare("Shadow")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].Shadow = std::stoi(valueName);
                else if (!keyName.compare("MarginL")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].MarginL = std::stoi(valueName);
                else if (!keyName.compare("MarginR")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].MarginR = std::stoi(valueName);
                else if (!keyName.compare("MarginV")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].MarginV = std::stoi(valueName);
                else if (!keyName.compare("Start")) {
                    strcpy(lib->AssglTrackItem[lib->AssglTrackCounts].Start , valueName.c_str());
                    lib->AssglTrackItem[lib->AssglTrackCounts].StartTime = timeStrFormatToMs(valueName);
                }
                else if (!keyName.compare("End")) {
                    strcpy(lib->AssglTrackItem[lib->AssglTrackCounts].End , valueName.c_str());
                    long long EndTime = timeStrFormatToMs(valueName);
                    lib->AssglTrackItem[lib->AssglTrackCounts].Duration = EndTime - lib->AssglTrackItem[lib->AssglTrackCounts].StartTime;
                }
                else if (!keyName.compare("FigureStyle")) 
                    strcpy(lib->AssglTrackItem[lib->AssglTrackCounts].FigureStyle , valueName.c_str());
                else if (!keyName.compare("EffectStyle")) 
                    strcpy(lib->AssglTrackItem[lib->AssglTrackCounts].EffectStyle , valueName.c_str());
                else if (!keyName.compare("ScaleX")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].ScaleX = std::stoi(valueName);
                else if (!keyName.compare("ScaleY")) 
                    lib->AssglTrackItem[lib->AssglTrackCounts].ScaleY = std::stoi(valueName);
                else if (!keyName.compare("PosX"))
                    lib->AssglTrackItem[lib->AssglTrackCounts].PosX = std::stoi(valueName);
                else if (!keyName.compare("PosY"))
                    lib->AssglTrackItem[lib->AssglTrackCounts].PosY = std::stoi(valueName);
                else if (!keyName.compare("Text"))
                    strcpy(lib->AssglTrackItem[lib->AssglTrackCounts].Text , valueName.c_str());
            }
            
            if (indexof == STRING(lib->EventFormat).length()){
                break;
            }
            indexofPre = (indexof += 1);
            valueIndexofPre = (valueIndexof += 1);
            
        }while(1);
    }
	return remark;
}

std::string parseScriptInfo(AssglLib *lib, std::string txtData){
	std::string remark;
    if (!strncmp(txtData.c_str(), "PlayResX:", 9)){
        lib->PlayResX = std::stoi(txtData.substr(9,txtData.length()-9));
    }
    else if (!strncmp(txtData.c_str(), "PlayResY:", 9)){
        lib->PlayResY = std::stoi(txtData.substr(9,txtData.length()-9));
    }

    return "";
}



void processLine(AssglLib *lib, char* str){
    skip_spaces(&str);
    std::string strs = std::string(str);

    if (!strs.compare("[Script Info]")){
        lib->State = PST_INFO;
    }
    else if(!strs.compare("[Events]")){
        lib->State = PST_EVENTS;
    }else{
        switch (lib->State)
        {
        case PST_INFO:
            parseScriptInfo(lib,strs);
            break;
        case PST_EVENTS:
            parseEvent(lib,strs);
            break;
        default:
            break;
        }
    }
    return ;
}

std::string parseTxtData(AssglLib *lib, std::string txtData)
{
	std::string remark;

	char *p = (char*)txtData.c_str();
    while (1) {
        char *q;
        while (1) {
            if ((*p == '\r') || (*p == '\n'))
                ++p;
            else if (p[0] == '\xef' && p[1] == '\xbb' && p[2] == '\xbf')
                p += 3;         // U+FFFE (BOM)
            else
                break;
        }
        for (q = p; ((*q != '\0') && (*q != '\r') && (*q != '\n')); ++q) {
        };
        if (q == p)
            break;
        if (*q != '\0')
            *(q++) = '\0';
		
		//========start============
		// std::cout << "p:" << p << std::endl;
        processLine(lib, p);
		//========end==============
        if (*q == '\0')
            break;
        p = q;
    }
	
	return std::string();
}
